<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <title>文档</title>
  <link href="../css/semantic/semantic.min.css" rel="stylesheet">
  <link href="../css/markdown.css" rel="stylesheet">
  <link href="../css/wtxynavigation.css" rel="stylesheet">
  <script src="../js/jquery.min.js"></script>
  <script type="text/javascript" src="../js/include.js"></script>
  <style>
    body{padding-top:0;background:#f7f7f7}
    body>.ui.container{width:100%;padding:0}
    #project-title{background:#6e6e6e;width:100%;line-height:3.572rem;color:#fff;font-size:1.2rem}
    #project-title .title-wrap{font-weight:700;padding:0 12px;width:100%;max-width:1366px!important;min-width:900px;margin:0 auto}
    #project-title .left,#project-title right{display:inline-block}
    #project-title .right{float:right}
    #project-title .right .wiki-actions .menu{left:auto;right:0;margin-top:.4em!important}
    #wiki-preview-container{width:100%;max-width:1366px!important;min-width:900px;padding:0;border:1px solid #e3e9ed;border-top:0}
    #wiki-preview>.ui.segment{margin-top:0;padding:1rem;padding-left:0;border:0}
    .hover-places{display:inline-block}
    #page-detail{width:60%;margin:0 auto}
    #page-detail .title{font-weight:700;font-size:24px;padding:12px 0;border-bottom:1px solid #ccc}
    #page-detail .content{margin-top:15px}
    .content p{word-wrap:break-word}
    #wiki-parent,#wiki-title,#wikis{display:none}
    .ui.grid{padding:0!important}
    #ex-all{cursor:pointer;color:#537c8d}
  </style>
</head>
<body>
  <div class="ui container">

    <div id="wtxyNav"></div>

    <div class="ui container" id="wiki-preview-container">
      <div id="wiki-preview">
        <div class="ui segment">
          <div id="page-detail" class="markdown-body">
            <div class='title'>7.使用了FMDatabaseQueue还是有崩溃问题</div><div class='content'><h1>
<a id="使用了fmdatabasequeue还是有崩溃问题" class="anchor" href="#%E4%BD%BF%E7%94%A8%E4%BA%86fmdatabasequeue%E8%BF%98%E6%98%AF%E6%9C%89%E5%B4%A9%E6%BA%83%E9%97%AE%E9%A2%98"></a>使用了FMDatabaseQueue还是有崩溃问题?</h1>
<p>参考: <a href="https://juejin.cn/post/6844903768975228942">掘金-CRMO-从FMDB线程安全问题说起</a></p>
<h2>
<a id="描述" class="anchor" href="#%E6%8F%8F%E8%BF%B0"></a>描述</h2>
<h3>
<a id="threading-mode-编译选项" class="anchor" href="#threading-mode-%E7%BC%96%E8%AF%91%E9%80%89%E9%A1%B9"></a>threading mode 编译选项</h3>
<p>SQLite threading mode 编译选项的<a href="https://www.sqlite.org/compile.html#threadsafe">官方文档</a></p>
<p>编译时，通过配置项<code>SQLITE_THREADSAFE</code>可以配置 SQLite 在多线程环境下是否安全。有三个可选项：</p>
<ul>
<li>0，对应 <code>Single-thread</code> ，编译时所有互斥锁代码会被删除掉，SQLite 在多线程环境下不安全。</li>
<li>1，对应 <code>Serialized</code>，在多线程环境下安全，如果不手动指定，这是默认选项</li>
<li>2，对应 <code>Multi-thread</code> ，在大部分情况下多线程环境安全，不安全情况：有两个线程同时尝试使用相同数据库连接（或从该数据库连接派生的任何预处理语句 Prepared Statements）</li>
</ul>
<p>除了编译时可以指定 threading mode ，还可以通过函数 <code>sqlite3_config()</code> （start-time ）改变全局的 threading mode 或者通过<code>sqlite3_open_v2()</code> （run-time）改变某个数据库连接的 threading mode。</p>
<p>但是如果编译时配置了<code>SQLITE_THREADSAFE = 0</code>，编译时所有线程安全代码都被优化掉了，就不能再切换到多线程模式了。</p>
<p>有了前面的知识，我们就可以分析问题一了。调用函数 <code>sqlite3_threadsafe()</code> 可以获取编译时的配置项，我们可以用这个函数获取系统自带的 SQLite 在编译时的配置，结论是2（Multi-thread）。</p>
<h1>
<a id="1-系统自带的-sqlite-在不做任何配置的情况下不是完全线程安全的当然可以手动将模式切换到-serialized-就可以实现完全线程安全了" class="anchor" href="#1-%E7%B3%BB%E7%BB%9F%E8%87%AA%E5%B8%A6%E7%9A%84-sqlite-%E5%9C%A8%E4%B8%8D%E5%81%9A%E4%BB%BB%E4%BD%95%E9%85%8D%E7%BD%AE%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E4%B8%8D%E6%98%AF%E5%AE%8C%E5%85%A8%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E7%9A%84%E5%BD%93%E7%84%B6%E5%8F%AF%E4%BB%A5%E6%89%8B%E5%8A%A8%E5%B0%86%E6%A8%A1%E5%BC%8F%E5%88%87%E6%8D%A2%E5%88%B0-serialized-%E5%B0%B1%E5%8F%AF%E4%BB%A5%E5%AE%9E%E7%8E%B0%E5%AE%8C%E5%85%A8%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E4%BA%86"></a>1. 系统自带的 <code>SQLite</code> 在不做任何配置的情况下不是完全线程安全的。当然可以手动将模式切换到 <code>Serialized</code> 就可以实现完全线程安全了</h1>
<h3>
<a id="1" class="anchor" href="#1"></a>1.</h3>
<h1>
<a id="答" class="anchor" href="#%E7%AD%94"></a>答:</h1>
<ol>
<li>手动将模式切换到 <code>Serialized</code>
</li>
</ol>
<pre><code>
// 方案一：全局设置模式
sqlite3_config(SQLITE_CONFIG_SERIALIZED);


</code></pre>
<ol start="2">
<li>使用 <code>while</code> 循环遍历 <code>FMResultSet</code>,<code>[FMResultSet next]</code> 遍历到最后会调用 <code>[FMResultSet close]</code>
</li>
<li>一定要用 <code>if ([result next])</code> ，手动加上 <code>[FMResultSet close]</code>
</li>
</ol></div>
          </div>
        </div>
      </div>
      </div>
  </div>
</body>
</html>